import JSEncrypt from 'jsencrypt';

// 16进制转byte数组

function hexToBytes(hex) {
  for (var bytes = [], c = 0; c < hex.length; c += 2)
    bytes.push(parseInt(hex.substr(c, 2), 16));
  return bytes;
}

// byte数组转16进制

function bytesToHex(bytes) {
  for (var hex = [], i = 0; i < bytes.length; i++) {
    hex.push((bytes[i] >>> 4).toString(16));
    hex.push((bytes[i] & 0xF).toString(16));
  }
  return hex.join("");
};


const rsaUtil = {
  //RSA 位数，这里要跟后端对应
  bits: 1024,

  //当前JSEncrypted对象
  thisKeyPair: {},

  //生成密钥对(公钥和私钥)
  genKeyPair: function (bits = rsaUtil.bits) {
    let genKeyPair = {};
    rsaUtil.thisKeyPair = new JSEncrypt({
      default_key_size: bits
    });

    //获取私钥
    genKeyPair.privateKey = rsaUtil.thisKeyPair.getPrivateKey();

    //获取公钥
    genKeyPair.publicKey = rsaUtil.thisKeyPair.getPublicKey();

    return genKeyPair;
  },

  //公钥加密
  encrypt: function (plaintext, publicKey) {
    if (plaintext instanceof Object) {
      //1、JSON.stringify
      plaintext = JSON.stringify(plaintext)
    }
    publicKey && rsaUtil.thisKeyPair.setPublicKey(publicKey);
    return rsaUtil.thisKeyPair.encrypt(JSON.stringify(plaintext));
  },

  //私钥解密
  decrypt: function (ciphertext, privateKey) {
    privateKey && rsaUtil.thisKeyPair.setPrivateKey(privateKey);
    let decString = rsaUtil.thisKeyPair.decrypt(ciphertext);
    if (decString.charAt(0) === "{" || decString.charAt(0) === "[") {
      //JSON.parse
      decString = JSON.parse(decString);
    }
    return decString;
  },
  encryptLong2: function (string) {
    var k = rsaUtil.thisKeyPair.getPublicKey();
    try {
      var ct = ""; //RSA每次加密最大117bytes，需要辅助方法判断字符串截取位置
      //1.获取字符串截取点
      var bytes = new Array();
      bytes.push(0);
      var byteNo = 0;
      var len, c;
      len = string.length;
      var temp = 0;
      for (var i = 0; i < len; i++) {
        c = string.charCodeAt(i);
        if (c >= 0x010000 && c <= 0x10FFFF) {
          byteNo += 4;
        } else if (c >= 0x000800 && c <= 0x00FFFF) {
          byteNo += 3;
        } else if (c >= 0x000080 && c <= 0x0007FF) {
          byteNo += 2;
        } else {
          byteNo += 1;
        }
        if ((byteNo % 117) >= 114 || (byteNo % 117) == 0) {
          if (byteNo - temp >= 114) {
            bytes.push(i);
            temp = byteNo;
          }
        }
      }
      //2.截取字符串并分段加密
      if (bytes.length > 1) {
        for (var i = 0; i < bytes.length - 1; i++) {
          var str;
          if (i == 0) {
            str = string.substring(0, bytes[i + 1] + 1);
          } else {
            str = string.substring(bytes[i] + 1, bytes[i + 1] + 1);
          }
          var t1 = k.encrypt(str);
          ct += t1;
        };
        if (bytes[bytes.length - 1] != string.length - 1) {
          var lastStr = string.substring(bytes[bytes.length - 1] + 1);
          ct += k.encrypt(lastStr);
        }
        return hexToBytes(ct);
      }
      var t = k.encrypt(string);
      var y = hexToBytes(t);
      return y;
    } catch (ex) {
      return false;
    }
  },
  utf8ByteToUnicodeStr: function (utf8Bytes) {
    var unicodeStr = "";
    for (var pos = 0; pos < utf8Bytes.length;) {
      var flag = utf8Bytes[pos];
      var unicode = 0;
      if ((flag >>> 7) === 0) {
        unicodeStr += String.fromCharCode(utf8Bytes[pos]);
        pos += 1;
      } else if ((flag & 0xFC) === 0xFC) {
        unicode = (utf8Bytes[pos] & 0x3) << 30;
        unicode |= (utf8Bytes[pos + 1] & 0x3F) << 24;
        unicode |= (utf8Bytes[pos + 2] & 0x3F) << 18;
        unicode |= (utf8Bytes[pos + 3] & 0x3F) << 12;
        unicode |= (utf8Bytes[pos + 4] & 0x3F) << 6;
        unicode |= (utf8Bytes[pos + 5] & 0x3F);
        unicodeStr += String.fromCharCode(unicode);
        pos += 6;
      } else if ((flag & 0xF8) === 0xF8) {
        unicode = (utf8Bytes[pos] & 0x7) << 24;
        unicode |= (utf8Bytes[pos + 1] & 0x3F) << 18;
        unicode |= (utf8Bytes[pos + 2] & 0x3F) << 12;
        unicode |= (utf8Bytes[pos + 3] & 0x3F) << 6;
        unicode |= (utf8Bytes[pos + 4] & 0x3F);
        unicodeStr += String.fromCharCode(unicode);
        pos += 5;
      } else if ((flag & 0xF0) === 0xF0) {
        unicode = (utf8Bytes[pos] & 0xF) << 18;
        unicode |= (utf8Bytes[pos + 1] & 0x3F) << 12;
        unicode |= (utf8Bytes[pos + 2] & 0x3F) << 6;
        unicode |= (utf8Bytes[pos + 3] & 0x3F);
        unicodeStr += String.fromCharCode(unicode);
        pos += 4;
      } else if ((flag & 0xE0) === 0xE0) {
        unicode = (utf8Bytes[pos] & 0x1F) << 12;;
        unicode |= (utf8Bytes[pos + 1] & 0x3F) << 6;
        unicode |= (utf8Bytes[pos + 2] & 0x3F);
        unicodeStr += String.fromCharCode(unicode);
        pos += 3;
      } else if ((flag & 0xC0) === 0xC0) { //110
        unicode = (utf8Bytes[pos] & 0x3F) << 6;
        unicode |= (utf8Bytes[pos + 1] & 0x3F);
        unicodeStr += String.fromCharCode(unicode);
        pos += 2;
      } else {
        unicodeStr += String.fromCharCode(utf8Bytes[pos]);
        pos += 1;
      }
    }
    return unicodeStr;
  },
  decryptLong2: function (string) {
    var k = rsaUtil.thisKeyPair.getPrivateKey();
    var MAX_DECRYPT_BLOCK = 128; //分段解密最大长度限制为128字节
    try {
      var ct = "";
      var t1;
      var bufTmp;
      var hexTmp;
      var str = bytesToHex(string); //这块可能有些没有必要，因为sting参数已经及转为byte数组
      var buf = hexToBytes(str);
      var inputLen = buf.length;
      //开始长度
      var offSet = 0;
      //结束长度
      var endOffSet = MAX_DECRYPT_BLOCK;
      //分段解密
      while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
          bufTmp = buf.slice(offSet, endOffSet);
          hexTmp = bytesToHex(bufTmp);
          t1 = k.decrypt(hexTmp);
          ct += t1;
          console.log('分段' + offSet)
          console.log(hexTmp)
          console.log(t1)
        } else {
          bufTmp = buf.slice(offSet, inputLen);
          hexTmp = bytesToHex(bufTmp);
          t1 = k.decrypt(hexTmp);
          ct += t1;
          console.log('分段' + offSet)
          console.log(hexTmp)
          console.log(t1)
        }
        offSet += MAX_DECRYPT_BLOCK;
        endOffSet += MAX_DECRYPT_BLOCK;
      }
      return ct;
    } catch (ex) {
      return false;
    }
  },
};

export default rsaUtil;